package main

import ( "flag"; 
		"fmt"; 
		"os"; 
		"bufio";
		"container/vector";
		"sort";
		"./clustersolution";
		"./clusterpoint";
		"./clustersync";
		"./clustermeans");

const (
	DefaultSolutions = 1000;
	DefaultSteps = 100;
	DefaultClusters = 10;
)

//Parse input flags
var datapath = flag.String("f", "", "Data File")
var numpoints = flag.Int("n", DefaultSolutions, "Solution Points")
var classes = flag.Int("k", DefaultClusters, "Cluters")
var steps = flag.Int("i", DefaultSteps, "Number Steps")
var mode = flag.Int("m",0,"Mode: 0=PSO, 1=Kmeans");

//Main Method
func main() {
   flag.Parse();
   rawhandle,err := os.Open(*datapath,os.O_RDONLY,0);
   if(err != nil) {fmt.Println(err); return;}
   bufhandle := bufio.NewReader(rawhandle);
   
   //Read in Data
   points := new(vector.Vector);
   for true {
	   line,err := bufhandle.ReadString('\n');
	   if(err != nil) { break; }
	   points.Push(clusterpoint.ParseLine(line));
   }
   rawhandle.Close();
   
   //Sort the Data
   sort.Sort(points);
   cp := clusterpoint.Compress(points);
   if *mode == 0 {
	  pso(cp);
   } else if *mode == 1 {
      kmeans(cp);
   }
}

func pso(cp *vector.Vector) {  
   //Initialize Solution Vectors
   dimensions := cp.Len();
   solutions := new(vector.Vector);
   for i:= 0; i < *numpoints; i++ {
      sln := clustersolution.MakeSolution(dimensions,*classes,cp);
      solutions.Push(sln);
   }
  
   //Make the communication server
   reqChan, signalChan := clustersync.StartServer();
   
   //Run them
   sem := make(chan int, *numpoints);
   for v := range solutions.Iter() {
      sln := v.(*clustersolution.ClusterSolution);
      go sln.Run(reqChan,*steps,sem);
   }
   
   //Rejoin threads
   for i:=0; i < *numpoints; i++ {
      <-sem;
   }
   
   //Get the best solution
   var quit clustersync.SignalChan;
   signalChan <- &quit;
   best := <-signalChan;
   
   //Print out the fitness
   fmt.Println("Best Fitness: ", best.Best.Fitness);
}

func kmeans(cp *vector.Vector) {
   dimensions := cp.Len();
   sln := clustersolution.MakeSolution(dimensions,*classes,cp);
   best := clustermeans.Kmeans(sln,*steps);
   fmt.Println("Best Fitness: ", best.Fitness);
}
